/*
 * Copyright (C) 2025 Tsingteng MicroSystem
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * @file ce_manager.c
 * @brief 卡模拟管理模块实现
 */

#include "nci_feature.h"
#if IS_FEATURE_ON(NCI_FEATURE_CE)

#include "nci_module.h"
#include "nci_task.h"
#include "data_int.h"
#include "nci_cfg.h"
#include "discover_int.h"
#include "nfa_ce.h"
#include "ce_int.h"
#include "ce_techs.h"

static tNCI_CE_MANAGER s_ce = {
    .enabled = false,
    .lock = MUTEX_INIT_VAL("ce")
};

#define GET_CE_LOCK(status) \
    if (osi_mutex_lock(&s_ce.lock) != NFC_STATUS_OK) { \
        NFCLOG_E("get ce lock failed"); \
        return status; \
    }

#define RELEASE_CE_LOCK() \
    if (osi_mutex_unlock(&s_ce.lock) != NFC_STATUS_OK) { \
        NFCLOG_E("ce unlock failed"); \
    }

#if IS_FEATURE_ON(NCI_FEATURE_CE_DH)
/**
 * @brief 注册监听
 *
 * @param[in] id 监听ID
 * @param[in] param 监听参数
 *
 * @return 成功返回NCI_STATUS_OK，失败返回错误码
 */
tNCI_STATUS nfa_ce_register_listen(tNCI_CE_LISTEN_ID *id, tNCI_CE_LISTEN_PARAM *param) {
    OSI_CHK_PARAM_INVALID(!s_ce.enabled, return NCI_STATUS_EXT_NOT_INITIALIZED);
    OSI_CHK_PARAM_INVALID(!id, return NCI_STATUS_EXT_INVALID_PARAM);
    OSI_CHK_PARAM_INVALID(!param, return NCI_STATUS_EXT_INVALID_PARAM);

    NFCLOG_I("Register listen tech : 0x%02x", id->tech);
    tNCI_CE_ACTS* p_acts = ce_utils_get_acts(id->tech);
    if (!p_acts) {
        NFCLOG_E("Actions not found");
        return NCI_STATUS_CE_GET_ACTS_FAILED;
    }

    GET_CE_LOCK(NCI_STATUS_EXT_GET_LOCK_FAILED);
    tNCI_STATUS ret = p_acts->register_listen(id, param);
    RELEASE_CE_LOCK();
    return ret;
}

/**
 * @brief 注销监听
 *
 * @param[in] id 监听ID
 *
 * @return 成功返回NCI_STATUS_OK，失败返回错误码
 */
tNCI_STATUS nfa_ce_unregister_listen(tNCI_CE_LISTEN_ID *id) {
    OSI_CHK_PARAM_INVALID(!s_ce.enabled, return NCI_STATUS_EXT_NOT_INITIALIZED);
    OSI_CHK_PARAM_INVALID(!id, return NCI_STATUS_EXT_INVALID_PARAM);

    NFCLOG_I("Unregister listen tech : 0x%02x", id->tech);
    tNCI_CE_ACTS* p_acts = ce_utils_get_acts(id->tech);
    if (!p_acts) {
        NFCLOG_E("Actions not found");
        return NCI_STATUS_CE_GET_ACTS_FAILED;
    }

    GET_CE_LOCK(NCI_STATUS_EXT_GET_LOCK_FAILED);
    tNCI_STATUS ret = p_acts->unregister_listen(id);
    RELEASE_CE_LOCK();
    return ret;
}

/**
 * @brief CE发送数据处理函数
 *
 * @param p_data 指向要传输的数据的指针.
 * @param len 要传输的数据长度.
 *
 * @return 传输成功返回NCI_STATUS_OK，失败返回错误码
 */
tNCI_STATUS nfa_ce_transmit(uint8_t *p_data, uint16_t len) {
    OSI_CHK_PARAM_INVALID(!s_ce.enabled, return NCI_STATUS_EXT_NOT_INITIALIZED);
    OSI_CHK_PARAM_INVALID(!p_data, return NCI_STATUS_EXT_INVALID_PARAM);
    OSI_CHK_PARAM_INVALID(len == 0, return NCI_STATUS_EXT_INVALID_PARAM);
    GET_CE_LOCK(NCI_STATUS_EXT_GET_LOCK_FAILED);
    tNCI_STATUS ret = NCI_STATUS_EXT_FAILED;
    tNCI_BUF *cmd = NULL;

    cmd = alloc_nci_buf_with_cap(0, len);
    ARRAY_TO_BUF(cmd, p_data, len);

    ret = rf_transmit_async(cmd);
    if (ret != NCI_STATUS_OK) {
        NFCLOG_E("nci data channel transmit failed");
    }
    free_nci_buf(cmd);
    RELEASE_CE_LOCK();
    return ret;
}
#endif // IS_FEATURE_ON(NCI_FEATURE_CE_DH)

/**
 * @brief 获取CE管理模块实例
 *
 * @return 返回CE管理模块实例指针
 */
tNCI_CE_MANAGER *ce_get_instance(void) {
    return &s_ce;
}

/**
 * @brief 根据field ntf更新CE field状态，并通知回调
 *
 * @param field 字段值，用于确定field状态（on/off）
 * @return true表示处理成功
 */
static bool ce_task_field_info(uint8_t field) {
    tNCI_CE_INFO info;
    info.field_on = ((field ==  0x01) ? true : false);
    NFCLOG_D("field %s", info.field_on == true ? "on" : "off");
    s_ce.cback(NCI_CE_EVT_FIELD_INFO, &info);
    return true;
}

#if IS_FEATURE_ON(NCI_FEATURE_CE_DH)
/**
 * @brief 接收激活事件task，判断激活tech类型，并通知回调
 *
 * @param p_params 指向包含激活参数的结构体指针
 * @return 如果是激活事件返回true；否则返回false
 */
static bool ce_task_activated(tNCI_RF_INTF_ACTIVATED_PARAMS *p_params) {
    OSI_CHK_PARAM_INVALID(!p_params, return false);
    tNCI_CE_INFO info;
    if (p_params->activation_tech_mode == NCI_RF_TECH_F_PASSIVE_LISTEN_MODE) {
        s_ce.technology = NCI_CE_T3T;
    } else if (p_params->activation_tech_mode == NCI_RF_TECH_A_PASSIVE_LISTEN_MODE ||
               p_params->activation_tech_mode == NCI_RF_TECH_B_PASSIVE_LISTEN_MODE) {
        s_ce.technology = NCI_CE_T4T;
    } else {
        s_ce.technology = NCI_CE_NONE;
        NFCLOG_E("Invalid activation_tech_mode, mode = %u", p_params->activation_tech_mode);
        return false;
    }
    info.technology = s_ce.technology;
    NFCLOG_D("technology = %u", info.technology);
    s_ce.cback(NCI_CE_EVT_ACTIVATED, &info);
    return true;
}

/**
 * @brief 接收去激活事件task，判断激活tech类型，并通知回调
 *
 * @return 返回true，表示已通知回调去激活
 */
static bool ce_task_deactivate() {
    tNCI_CE_INFO info;
    info.technology = s_ce.technology;
    NFCLOG_D("technology = %u", info.technology);
    s_ce.cback(NCI_CE_EVT_DEACTIVATE, &info);
    s_ce.technology = NCI_CE_NONE;
    return true;
}
#endif // IS_FEATURE_ON(NCI_FEATURE_CE_DH)

/**
 * @brief CE管理模块异步事件处理完成后，清理参数
 *
 * @param what 事件类型，用于标识发生了哪种事件
 * @param arg1 未使用，保留参数，可用于未来扩展
 * @param arg2 未使用，保留参数，可用于未来扩展
 * @param args 指向需要清理的资源（例如内存）的指针
 */
static void ce_task_cleaner(uint32_t what, uint32_t arg1, uint64_t arg2, void* args) {
    if (args) {
        NFCLOG_D("what= %d, arg1 = %d, arg2 = %" PRIu64, what, arg1, arg2);
        osi_free(args);
    }
}

/**
 * @brief CE管理模块异步事件处理函数
 *
 * @param what 事件类型
 * @param arg1 事件相关的第一个参数
 * @param arg2 事件相关的第二个参数（本函数中未使用）
 * @param args 事件相关的附加参数
 *
 * @return 返回true表示事件成功处理，其他返回false
 */
static bool ce_task_handler(uint32_t what, uint32_t arg1, uint64_t arg2, void* args) {
    (void) arg2;
    bool ret = true;
    NFCLOG_D("event = 0x%08X", what);
    tNCI_TASK_EVT event = (tNCI_TASK_EVT)what;

    switch (event) {
    case NCI_TASK_EVT_CE_FIELD_INFO:
        ret = ce_task_field_info(arg1);
        break;

    case NCI_TASK_EVT_CE_ACTIVATED:
#if IS_FEATURE_ON(NCI_FEATURE_CE_DH)
        ret = ce_task_activated(args);
#endif // IS_FEATURE_ON(NCI_FEATURE_CE_DH)
        break;

    case NCI_TASK_EVT_CE_DEACTIVATED:
#if IS_FEATURE_ON(NCI_FEATURE_CE_DH)
        ret = ce_task_deactivate();
#endif // IS_FEATURE_ON(NCI_FEATURE_CE_DH)
        break;

    default:
        NFCLOG_D("Unsupported event : %u", event);
        ret = false;
        break;
    }

    return ret;
}

/**
 * @brief CE数据接收处理函数
 *
 * @param[in] conn_id 连接标识符
 * @param[in] p_data 指向需要处理的数据的指针
 * @param[in] len 表示需要处理的数据长度
 */
static void ce_receive_handler(uint8_t conn_id, const uint8_t *p_data, uint16_t len) {
    OSI_CHK_PARAM_INVALID(!p_data, return);
    OSI_CHK_PARAM_INVALID(len == 0, return);

    if (conn_id != NCI_DATA_CHANNEL_RF) {
        NFCLOG_E("Invalid conn_id, conn_id = %u", conn_id);
        return;
    }

    tNCI_CE_ACTS* p_acts = ce_utils_get_acts(s_ce.technology);
    if (p_acts) {
        p_acts->receive_handler(p_data, &len);
    }

#if IS_FEATURE_ON(NCI_FEATURE_CE_DH)
    tNCI_CE_INFO info;
    info.rcv.type = s_ce.technology;
    info.rcv.data.len  = len;
    info.rcv.data.buf = p_data;
    s_ce.cback(NCI_CE_EVT_DATA, &info);
#endif // IS_FEATURE_ON(NCI_FEATURE_CE_DH)
}

/**
 * @brief CE管理模块初始化
 *
 * @param p_cfg 指向配置结构体的指针，用于传递初始化所需的配置信息
 *
 * @return 传输成功返回NCI_STATUS_OK，失败返回错误码
 */
static tNCI_STATUS ce_init(const tNCI_MODULE_INIT_CFG *p_cfg) {
    if ((!p_cfg) || (!p_cfg->p_external_cfg) || (!p_cfg->p_external_cfg->ce_cback)) {
        NFCLOG_W("CE module does not need to be initialized");
        NFCLOG_D("ce_cback is %s", p_cfg->p_external_cfg->ce_cback == NULL ? "NULL" : "not NULL");
        return NCI_STATUS_OK;
    }
    tNCI_STATUS ret;

    NFCLOG_D("Enter");
    if (osi_mutex_init_with_attr(&s_ce.lock, true) != NFC_STATUS_OK) {
        NFCLOG_E("Init mutex failed");
        return NCI_STATUS_EXT_INIT_LOCK_FAILED;
    }

    s_ce.technology = NCI_CE_NONE;
    s_ce.cback = p_cfg->p_external_cfg->ce_cback;

#if IS_FEATURE_ON(NCI_FEATURE_CE_DH)
    ret = ce_t3t_init();
    if (ret != NCI_STATUS_OK) {
        NFCLOG_E("Init T3T failed");
        goto err_free_lock;
    }
    s_ce.listen_list = ce_list_create();
    if (!s_ce.listen_list) {
        NFCLOG_E("Create listen list failed");
        ret = NCI_STATUS_CE_LIST_NODE_FAILED;
        goto err_free_lock;
    }
#endif // IS_FEATURE_ON(NCI_FEATURE_CE_DH)

    ret = nci_task_register(ce_task_handler, ce_task_cleaner, NCI_TASK_EVT_CE_GROUP);
    if (ret != NCI_STATUS_OK) {
        NFCLOG_E("Register task failed, ret = %d", ret);
        goto err_free_list;
    }

    ret = data_register_cback(NCI_DATA_CHANNEL_RF, ce_receive_handler);
    if (ret != NCI_STATUS_OK) {
        NFCLOG_E("Register data cback failed, ret = %d", ret);
        goto err_unregister_task;
    }

    s_ce.enabled = true;
    NFCLOG_D("Exit");
    return NCI_STATUS_OK;
err_unregister_task:
    nci_task_unregister(NCI_TASK_EVT_CE_GROUP);
err_free_list:
#if IS_FEATURE_ON(NCI_FEATURE_CE_DH)
    ce_list_destroy(s_ce.listen_list);
err_free_lock:
#endif // IS_FEATURE_ON(NCI_FEATURE_CE_DH)
    osi_mutex_deinit(&s_ce.lock);
    NFCLOG_E("Exit, failed to init CE module, ret = %d", ret);
    return ret;
}

/**
 * @brief CE管理模块销毁
 *
 * @param is_shutdown 一个布尔值，表示是否是关机操作
 *
 * @return 只返回 NCI_STATUS_OK，表示操作成功
 */

static tNCI_STATUS ce_deinit(bool is_shutdown) {
    (void)is_shutdown;
    s_ce.enabled = false;
    osi_mutex_deinit(&s_ce.lock);
    nci_task_unregister(NCI_TASK_EVT_CE_GROUP);
    data_unregister_cback(NCI_DATA_CHANNEL_RF, ce_receive_handler);
#if IS_FEATURE_ON(NCI_FEATURE_CE_DH)
    ce_list_destroy(s_ce.listen_list);
#endif // IS_FEATURE_ON(NCI_FEATURE_CE_DH)
    osi_memset_s(&s_ce, sizeof(s_ce), 0x00, sizeof(s_ce));
    return NCI_STATUS_OK;
}

/**
 * @brief CE管理模块dump函数
 */
static void ce_dump(int fd) {
    (void)fd;
}

/**
 * @brief NFCCE管理模块定义
 */
tNCI_MODULE g_ce_manager = {
    .name = "CE_MANAGER",
    .init = ce_init,
    .deinit = ce_deinit,
    .dump = ce_dump,
};

#endif // IS_FEATURE_ON(NCI_FEATURE_CE)
